package com.lanhao.aot.moss;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import org.apache.commons.io.FileUtils;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lanhao.aot.aiui.websocket.DraftWithOrigin;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;

public class InteractiveCloudUtil {
	private static final Logger LOG = LoggerFactory.getLogger(InteractiveCloudUtil.class);
	public static final String REQUEST_URL = "ws://172.17.0.255:26000/createRec";
	public static final String APPID = "DZeBO8Xx";
	public static final String API_SECRET = "7ED5DEE2E323450ABD0BD57019F82B16";
	public static final String SCENE = "admin.robotInteraction";
	public static final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MTAxMjExNjksImRldmljZUlEIjoiMTIzNDU2Nzg5In0.kST51BaeRIl0S9w1T7It0NIgNHrLYdjR8goM5BSYne0";

	
//	public static final String APPID = "wZjW65gx";
//	public static final String API_SECRET = "89B1DEB3F68D4EAEA1DA98C19CD4C615";
//	public static final String SCENE = "admin.mossTest";
	
	// 每帧音频数据大小，单位字节
	private static final int CHUNCKED_SIZE = 1280;
	
	public static void main(String[] args) {
		try {
			URI url = new URI(REQUEST_URL);
			DraftWithOrigin draft = new DraftWithOrigin(getWebsocketUrlOrigin(REQUEST_URL));
			CountDownLatch countDownLatch = new CountDownLatch(1);
			MyWebSocketClient client = new MyWebSocketClient(url, draft, countDownLatch);
			client.connect();
			while (!client.getReadyState().equals(ReadyState.OPEN)) {
				Thread.sleep(50);
			}
			String filePath = "D:/pcm/byct.pcm";
			String streamId = UUID.fastUUID().toString(true);
//			String data = cn.hutool.core.codec.Base64.encode(new File(filePath));
//			sendIntentQuery(client, data, streamId);
			// 发送音频
			byte[] bytes = new byte[CHUNCKED_SIZE];
			try (RandomAccessFile raf = new RandomAccessFile(filePath, "r")) {
				int len = -1;
				while ((len = raf.read(bytes)) != -1) {
					if (len < CHUNCKED_SIZE) {
						bytes = Arrays.copyOfRange(bytes, 0, len);
					}
					sendIntentQuery(client, Base64.encode(bytes), streamId);
					Thread.sleep(40);
				}
//				send(client, END_FLAG.getBytes());
//				System.out.println("发送结束标识完成");
			} catch (Exception e) {
				e.printStackTrace();
			}
			// 等待交互完成
			countDownLatch.await();
			// 返回最终结果
			if (!client.isClosed()) {
				// 主动断开连接，如果不主动断开60秒无交互之后服务端会主动断开连接
				client.close(1000);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static String getWebsocketUrlOrigin(String websocketUrl) {
        websocketUrl = websocketUrl.replaceAll("ws[s]?://", "");
        return "http://" + websocketUrl.substring(0, websocketUrl.indexOf("/"));
    }
	
	private static class MyWebSocketClient extends WebSocketClient {

        private CountDownLatch countDownLatch;

        public MyWebSocketClient(URI serverUri, Draft protocolDraft, CountDownLatch countDownLatch) {
            super(serverUri, protocolDraft);
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void onOpen(ServerHandshake handshake) {
            // 会阻塞onMesage, 如果要在这里发送数据需要另起线程
            LOG.info("打开连接, code:" + handshake.getHttpStatusMessage());
        }

        @Override
        public void onMessage(String msg) {
			JSONObject rObject = JSON.parseObject(msg);
			JSONArray resultArray = rObject.getJSONArray("result");
			JSONObject resultObject = resultArray.getJSONObject(0);
			String sub = resultObject.getString("sub");
			if ("iat".equals(sub)) {
				LOG.info("语音转写返回结果：" + resultObject.toJSONString());
			} if ("moss".equals(sub)) {
				LOG.info("moss返回结果：" + resultObject.toJSONString());
			} else if ("bps".equals(sub)) {
				LOG.info("语义后处理返回结果：" + resultObject.toJSONString());
				JSONObject dataObject = resultObject.getJSONObject("data");
				JSONObject extraDataObject = dataObject.getJSONObject("extraData");
				if (extraDataObject != null) {
					String url = extraDataObject.getString("url");
					LOG.info("外部信源对应的播放地址：" + url);
				}
			} else if ("tts".equals(sub)){
//				LOG.info("收到TTS消息：" + msg);
				// 此处将tits的data数据透传到SDK端进行音频播放
			}
        	try {
        		FileUtils.write(new File("D:/pcm/msg.log"), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MS_PATTERN) + "收到消息：" + msg + "\r\n", "UTF-8", true);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
        }

        @Override
        public void onError(Exception e) {
        	LOG.info("连接发生错误：" + e.getMessage() + ", " + new Date());
            e.printStackTrace();
        }

        @Override
        public void onClose(int code, String message, boolean b) {
        	LOG.info("连接已关闭" + "," + new Date());
            countDownLatch.countDown();
        }

        @Override
        public void onMessage(ByteBuffer bytes) {
            try {
                String responseText = new String(bytes.array(), "utf-8");
                LOG.info("服务端返回：" + responseText);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }
	
	public static void sendIntentQuery(WebSocketClient wsClient, String data, String streamId) {
		JSONObject request = new JSONObject();
		request.put("app_id", APPID);
		
		request.put("data", data);
		request.put("scene", SCENE);
		request.put("debug", true);
		JSONObject sessionParams = new JSONObject();
		JSONObject abilityParams = new JSONObject();

		JSONObject iatParams = new JSONObject();
//		iatParams.put("endFlag", "true"); // 音频最后一帧的时候传true，其他时候传false
		iatParams.put("aue", "raw");
		iatParams.put("rate", "16k");
		iatParams.put("dwa", "wpgs"); // 引擎参数，是否获取中间结果
		iatParams.put("rst", "json");
		JSONObject bpsParams = new JSONObject();
		bpsParams.put("origin_url", "http://172.17.0.252:8183/semantic/rest/v1/semantic?uid=123456789&robotDevId=testRobotDeviceId&token=" + TOKEN);
		bpsParams.put("nlp_type", "json");
		bpsParams.put("nlp_result", "json");
		
		abilityParams.put("bps", bpsParams);
		abilityParams.put("iat", iatParams);
		
		sessionParams.put("abilityParams", abilityParams);
		request.put("sessionParams", sessionParams);

		LOG.info("发送指令，请求参数:{}", request.toJSONString());
		try {
    		FileUtils.write(new File("D:/pcm/msg.log"), DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MS_PATTERN) + "发送请求：" + request.toJSONString() + "\r\n", "UTF-8", true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		wsClient.send(request.toJSONString());
	}
}
